/*
** Copyright (C) 2010 Calin Radoni
**
** This file is part of CHScanner.
**
** CHScanner is free software: you can redistribute it and/or modify
** it under the terms of the GNU General Public License as published by
** the Free Software Foundation, either version 3 of the License, or
** (at your option) any later version.
**
** CHScanner is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with CHScanner. If not, see <http://www.gnu.org/licenses/>.
*/

#include "StdAfx.h"
#include ".\exportxml.h"

//---------------------------------------------------------------------------

ExportXML::ExportXML(void)
{
	outFile.m_hFile=CFile::hFileNull;
}

ExportXML::~ExportXML(void)
{
	EndExport();
}

//---------------------------------------------------------------------------

CString ExportXML::RemoveStupidChars(CString strIn)
{
	CString str;
	LPTSTR strBuff;
	int i, cnt;

	str = strIn;
	str.Replace(_T("<"), _T("&lt;"));
	str.Replace(_T(">"), _T("&gt;"));

	cnt = str.GetLength();
	strBuff = str.GetBuffer();
	for(i=0; i<cnt; i++)
		if(strBuff[i]<0x20 || strBuff[i]>0x7E)
			strBuff[i] = '.';
	str.ReleaseBuffer();

	return str;
}

//---------------------------------------------------------------------------

bool ExportXML::WriteLine(CString strIn, int tabCnt)
{
	CString str;
	bool res;
	int i;

	if(tabCnt<0) return false;

	str.Empty();

	for(i=0; i<tabCnt; i++)
		str += "\t";

	str += strIn;
	str += "\n";

	res = true;
	try{
		outFile.WriteString(str);
	}
	catch(...){
		res = false;
	}

	return res;
}

//---------------------------------------------------------------------------

bool ExportXML::BeginExport(ExportInfo *ei)
{
	CString str;
	bool res;

	if(ei==NULL) return false;

	if(!outFile.Open(ei->destFileName, CFile::modeCreate | CFile::modeWrite, NULL))
		return false;

	expHostId = 1;

	str = _T("<?xml version=\"1.0\" ?>");
	res = WriteLine(str, 0);
	if(!res) return false;

	str = _T("<?xml-stylesheet type=\"text/xsl\" href=\"CHScanner.xsl\"?>");
	res = WriteLine(str, 0);
	if(!res) return false;

	str.Empty();
	res = WriteLine(str, 0);
	if(!res) return false;

	str = _T("<CHScannerDoc>");
	res = WriteLine(str, 0);
	if(!res) return false;

	switch(ei->scanType){
		case __lstHunt :
			str.Format(_T("Hunt mode - %s"), ei->timeStamp);
			break;
		case __lstPasive :
			str.Format(_T("Passive scan - %s"), ei->timeStamp);
			break;
		case __lstActive :
			if(!ei->workCfg.xFileName.IsEmpty()) str = ei->workCfg.xFileName;
			else                                 str.Format(_T("Active scan - %s"), ei->timeStamp);
			break;
		default:
			str = ei->timeStamp;
			break;
	}
	res = AddTitle(str);
	if(!res) return false;

	res = AddVersion(ei->application, ei->version);
	if(!res) return false;

	res = AddTimeStamp(ei->timeStamp);
	if(!res) return false;

	switch(ei->scanType){
		case __lstHunt :
			str = _T("<workCfg type=\"hunt\">");
			res = WriteLine(str, 1);
			if(res){
				str = _T("</workCfg>");
				res = WriteLine(str, 1);
			}
			break;

		case __lstPasive :
			str = _T("<workCfg type=\"passive\">");
			res = WriteLine(str, 1);
			if(res){
				str = _T("</workCfg>");
				res = WriteLine(str, 1);
			}
			break;

		case __lstActive :
			res = AddWorkCfgInfo(&ei->workCfg);
			break;

		default:
			res = false;
	}
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddTitle(CString strIn)
{
	CString str;

	str  = _T("<pageTitle>");
	str += strIn;
	str += _T("</pageTitle>");
	return WriteLine(str, 1);
}

bool ExportXML::AddVersion(CString appNameIn, CString appVerIn)
{
	CString str;
	bool res;

	str = _T("<version>");
	res = WriteLine(str, 1);
	if(!res) return false;

	str = _T("<vApp>");
	str += appNameIn;
	str += _T("</vApp>");
	res = WriteLine(str, 2);
	if(!res) return false;

	str = _T("<vNumber>");
	str += appVerIn;
	str += _T("</vNumber>");
	res = WriteLine(str, 2);
	if(!res) return false;

	str = _T("</version>");
	res = WriteLine(str, 1);
	if(!res) return false;

	return true;
}

bool ExportXML::AddTimeStamp(CString strIn)
{
	CString str;

	str  = _T("<timestamp>");
	str += strIn;
	str += _T("</timestamp>");
	return WriteLine(str, 1);
}

bool ExportXML::AddWorkCfgInfo(WorkCfg* cfgIn)
{
	CString str;
	bool res;

	if(cfgIn==NULL) return false;

	str = _T("<workCfg type=\"active\">");
	res = WriteLine(str, 1);
	if(!res) return false;

	if(!cfgIn->xFileName.IsEmpty()){
		str = _T("<cFileName>");
		str += cfgIn->xFileName;
		str += _T("</cFileName>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!cfgIn->xDescription.IsEmpty()){
		str = _T("<cDescription>");
		str += cfgIn->xDescription;
		str += _T("</cDescription>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!cfgIn->xComment.IsEmpty()){
		str = _T("<cComment>");
		str += cfgIn->xComment;
		str += _T("</cComment>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	str = _T("<cAddressSpace>");
	str += cfgIn->xAddresses;
	str += _T("</cAddressSpace>");
	res = WriteLine(str, 2);
	if(!res) return false;

	str = _T("<cScanAll>");
	if(cfgIn->xScanAll) str += _T("everything");
	else                str += _T("alive hosts only");
	str += _T("</cScanAll>");
	res = WriteLine(str, 2);
	if(!res) return false;

	str = _T("<cScanOrder>");
	switch(cfgIn->xScanOrder){
		case __soNumeric :
			str += _T("scan in numeric order");
			break;
		case __soRandomized :
			str += _T("randomize scan order");
			break;
		default :
			str += _T("scan as entered");
			break;
	}
	str += _T("</cScanOrder>");
	res = WriteLine(str, 2);
	if(!res) return false;

	str.Format(_T("<cMaxSimScanG>%d</cMaxSimScanG>"), cfgIn->xMaxSimScan);
	res = WriteLine(str, 2);
	if(!res) return false;

	str.Format(_T("<cMaxSimScanD>%d</cMaxSimScanD>"), cfgIn->xMaxSimScanDns);
	res = WriteLine(str, 2);
	if(!res) return false;

	str.Format(_T("<cMaxSimScanI>%d</cMaxSimScanI>"), cfgIn->xMaxSimScanIcmp);
	res = WriteLine(str, 2);
	if(!res) return false;

	str.Format(_T("<cMaxWaitTime>%d</cMaxWaitTime>"), cfgIn->xMaxWaitTime);
	res = WriteLine(str, 2);
	if(!res) return false;

	str = _T("</workCfg>");
	res = WriteLine(str, 1);
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddNetBiosNames(MMachineInfo* mmi)
{
	CString str;
	bool res;
	int i;

	if(mmi==NULL) return true;
	if(mmi->nbNamesCnt<=0) return true;

	str = _T("<netBios>");
	res = WriteLine(str, 2);
	if(!res) return false;

	for(i=0; i<mmi->nbNamesCnt; i++){
		str.Format(_T("<netBiosName>%s</netBiosName>"), RemoveStupidChars(mmi->nbNames[i]));
		res = WriteLine(str, 3);
		if(!res) return false;
	}

	str = _T("</netBios>");
	res = WriteLine(str, 2);
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddSharesInfo(MMachineInfo* mmi)
{
	CString str;
	int i, cnt;
	MShareInfo *shareInfo;
	bool res;

	if(mmi==NULL) return false;

	cnt = mmi->GetShareInfoCount();
	if(cnt<0) return false;
	if(cnt==0) return true;

	mmi->SortShareInfo();

	str = _T("<shares>");
	res = WriteLine(str, 2);
	if(!res) return false;

	for(i=0; i<cnt; i++){
		shareInfo = mmi->GetShareInfo(i);
		if(shareInfo!=NULL){
			if(shareInfo->remark.GetLength()>0) str.Format("<shareInfo>%s - %s</shareInfo>", shareInfo->name, wd.GetShareTypeName(shareInfo->type));
			else                                str.Format("<shareInfo>%s - %s (%s)</shareInfo>", shareInfo->name, wd.GetShareTypeName(shareInfo->type), shareInfo->remark);
			res = WriteLine(str, 3);
			if(!res) return false;
		}
	}

	str = _T("</shares>");
	res = WriteLine(str, 2);
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddSnmpSysInfo(MMachineInfo* mmi)
{
	CString str;

	if(mmi==NULL) return true;
	if(mmi->snmpSysRec.IsEmpty()) return true;

	str = _T("<snmpSysInfo>");
	if(!WriteLine(str, 2)) return false;

	if(!mmi->snmpSysRec.sysDescription.IsEmpty()){
		str.Format(_T("<snmpSysInfoItem type=\"Description\">%s</snmpSysInfoItem>"), RemoveStupidChars(mmi->snmpSysRec.sysDescription));
		if(!WriteLine(str, 3)) return false;
	}

	if(!mmi->snmpSysRec.sysVendorOid.IsEmpty()){
		str.Format(_T("<snmpSysInfoItem type=\"VendorOID\">%s</snmpSysInfoItem>"), RemoveStupidChars(mmi->snmpSysRec.sysVendorOid));
		if(!WriteLine(str, 3)) return false;
	}

	if(!mmi->snmpSysRec.sysContact.IsEmpty()){
		str.Format(_T("<snmpSysInfoItem type=\"Contact\">%s</snmpSysInfoItem>"), RemoveStupidChars(mmi->snmpSysRec.sysContact));
		if(!WriteLine(str, 3)) return false;
	}

	if(!mmi->snmpSysRec.sysName.IsEmpty()){
		str.Format(_T("<snmpSysInfoItem type=\"Name\">%s</snmpSysInfoItem>"), RemoveStupidChars(mmi->snmpSysRec.sysName));
		if(!WriteLine(str, 3)) return false;
	}

	if(!mmi->snmpSysRec.sysLocation.IsEmpty()){
		str.Format(_T("<snmpSysInfoItem type=\"Location\">%s</snmpSysInfoItem>"), RemoveStupidChars(mmi->snmpSysRec.sysLocation));
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->snmpSysRec.sysUpTime>0){
		str.Format(_T("<snmpSysInfoItem type=\"UpTime\">%s</snmpSysInfoItem>"), DwTimeToDHMS(mmi->snmpSysRec.sysUpTime/100));
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->snmpSysRec.sysServices>0){
		str = _T("<snmpSysInfoItem type=\"Services\">");
		if(mmi->snmpSysRec.sysServices & 0x01) str += _T("1 ");
		if(mmi->snmpSysRec.sysServices & 0x02) str += _T("2 ");
		if(mmi->snmpSysRec.sysServices & 0x04) str += _T("3 ");
		if(mmi->snmpSysRec.sysServices & 0x08) str += _T("4 ");
		if(mmi->snmpSysRec.sysServices & 0x10) str += _T("5 ");
		if(mmi->snmpSysRec.sysServices & 0x20) str += _T("6 ");
		if(mmi->snmpSysRec.sysServices & 0x40) str += _T("7 ");
		str.Trim();
		str += _T("</snmpSysInfoItem>");
		if(!WriteLine(str, 3)) return false;
	}

	str = _T("</snmpSysInfo>");
	if(!WriteLine(str, 2)) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddDhcpInfo(MMachineInfo* mmi)
{
	CString str;
	int i, cnt;
	MDHCPOption* opt;

	if(mmi==NULL) return true;
	if(mmi->infoDHCP.isEmpty) return true;

	str = _T("<dhcpInfo>");
	if(!WriteLine(str, 2)) return false;

	if(mmi->infoDHCP.yiAddr!=0){
		str.Format(_T("<dhcpInfoItem type=\"yiAddr\">%s</dhcpInfoItem>"), DwToIpStr(mmi->infoDHCP.yiAddr));
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->infoDHCP.hLen!=0){
		str.Format(_T("<dhcpInfoItem type=\"chAddr\">%s</dhcpInfoItem>"), infoDescDHCP.DhcpMacToStr(mmi->infoDHCP.chAddr, mmi->infoDHCP.hLen));
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->infoDHCP.siAddr!=0){
		str.Format(_T("<dhcpInfoItem type=\"siAddr\">%s</dhcpInfoItem>"), DwToIpStr(mmi->infoDHCP.siAddr));
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->infoDHCP.giAddr!=0){
		str.Format(_T("<dhcpInfoItem type=\"giAddr\">%s</dhcpInfoItem>"), DwToIpStr(mmi->infoDHCP.giAddr));
		if(!WriteLine(str, 3)) return false;
	}

	cnt = mmi->infoDHCP.optList.GetSize();
	for(i=0; i<cnt; i++){
		opt = mmi->infoDHCP.optList.GetByIdx(i);
		if(opt!=NULL){
			str = _T("<dhcpInfoOption>");
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<dhcpInfoOptionId>%u</dhcpInfoOptionId>"), opt->optionId);
			if(!WriteLine(str, 4)) return false;
			str.Format(_T("<dhcpInfoOptionName>%s</dhcpInfoOptionName>"), infoDescDHCP.FormatDhcpOptionName(opt));
			if(!WriteLine(str, 4)) return false;
			str.Format(_T("<dhcpInfoOptionValue>%s</dhcpInfoOptionValue>"), infoDescDHCP.FormatDhcpOptionValue(opt));
			if(!WriteLine(str, 4)) return false;

			str = _T("</dhcpInfoOption>");
			if(!WriteLine(str, 3)) return false;
		}
	}

	str = _T("</dhcpInfo>");
	if(!WriteLine(str, 2)) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddPromiscResults(MMachineInfo* mmi)
{
	CString str;

	if(mmi==NULL) return true;
	if(mmi->address.promiscState==0) return true;

	str = _T("<promiscInfo>");
	if(!WriteLine(str, 2)) return false;

	if(mmi->address.promiscState & 0x01){
		str = _T("<promiscInfoItem type=\"bCast47\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->address.promiscState & 0x02){
		str = _T("<promiscInfoItem type=\"bCast16\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->address.promiscState & 0x04){
		str = _T("<promiscInfoItem type=\"bCast8\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->address.promiscState & 0x08){
		str = _T("<promiscInfoItem type=\"GroupBit\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->address.promiscState & 0x10){
		str = _T("<promiscInfoItem type=\"mCast0\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	if(mmi->address.promiscState & 0x20){
		str = _T("<promiscInfoItem type=\"mCast1\"/>");
		if(!WriteLine(str, 3)) return false;
	}

	str = _T("</promiscInfo>");
	if(!WriteLine(str, 2)) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddIgmpInfo(MMachineInfo* mmiIn, MKMcast4List* mcast4ListIn)
{
	CString str, mcast4Name;
	int i, cnt;
	MIGMPPacket *mpg;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetIgmpPackCount();
	if(cnt==0) return true;

	str = _T("<igmpInfo>");
	if(!WriteLine(str, 2)) return false;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetIgmpPack(i);
		if(mpg!=NULL){
			mcast4Name.Empty();
			if(mpg->addr.GetD()!=0)
				if(mcast4ListIn!=NULL)
					mcast4Name = mcast4ListIn->GetName(mpg->addr.GetD());

			if(mcast4Name.IsEmpty()){
				if(mpg->recordType!=0) str.Format(_T("<igmpInfoItem type=\"%u\" recordType=\"%u\">%s</igmpInfoItem>"), mpg->type, mpg->recordType, mpg->addr.GetS());
				else                   str.Format(_T("<igmpInfoItem type=\"%u\">%s</igmpInfoItem>"), mpg->type, mpg->addr.GetS());
			}
			else{
				if(mpg->recordType!=0) str.Format(_T("<igmpInfoItem type=\"%u\" assignment=\"%s\" recordType=\"%u\">%s</igmpInfoItem>"), mpg->type, mcast4Name, mpg->recordType, mpg->addr.GetS());
				else                   str.Format(_T("<igmpInfoItem type=\"%u\" assignment=\"%s\">%s</igmpInfoItem>"), mpg->type, mcast4Name, mpg->addr.GetS());
			}

			if(!WriteLine(str, 3)) return false;
		}
	}

	str = _T("</igmpInfo>");
	if(!WriteLine(str, 2)) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddGVRPInfo(MMachineInfo* mmiIn)
{
	CString str;
	int i, cnt;
	int j, jnt;
	MGxRPPacket *mpg;
	MLEVRecord *rec;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetGxRPPackCount();
	if(cnt==0) return true;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetGxRPPack(i);
		if(mpg!=NULL){
			if(mGxRPDecoder.GetProtocolType(mpg)==__gxrpGvrp){
				str.Format(_T("<gvrpInfo name=\"%s %s\">"),
					mGxRPDecoder.GetProtocolName(mpg),
					mGxRPDecoder.GetAttributeTypeName(mpg));
				if(!WriteLine(str, 2)) return false;

				jnt = mpg->Attributes.GetSize();
				for(j=0; j<jnt; j++){
					rec = mpg->Attributes.GetByIdx(j);
					if(rec!=NULL){
						str.Format(_T("<gvrpInfoItem type=\"%s\">%s</gvrpInfoItem>"),
							mGxRPDecoder.GetAttributeEventName(rec->xEvent),
							mGxRPDecoder.GetAttributeValue(mpg, rec->xLength, rec->xValue[0], rec->xValue[1]));
						if(!WriteLine(str, 3)) return false;
					}
				}

				str = _T("</gvrpInfo>");
				if(!WriteLine(str, 2)) return false;
			}
		}
	}

	return true;
}

bool ExportXML::AddGMRPInfo(MMachineInfo* mmiIn)
{
	CString str;
	int i, cnt;
	int j, jnt;
	MGxRPPacket *mpg;
	MLEVRecord *rec;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetGxRPPackCount();
	if(cnt==0) return true;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetGxRPPack(i);
		if(mpg!=NULL){
			if(mGxRPDecoder.GetProtocolType(mpg)==__gxrpGmrp){
				str.Format(_T("<gmrpInfo name=\"%s %s\">"),
					mGxRPDecoder.GetProtocolName(mpg),
					mGxRPDecoder.GetAttributeTypeName(mpg));
				if(!WriteLine(str, 2)) return false;

				jnt = mpg->Attributes.GetSize();
				for(j=0; j<jnt; j++){
					rec = mpg->Attributes.GetByIdx(j);
					if(rec!=NULL){
						str.Format(_T("<gmrpInfoItem type=\"%s\">%s</gvrpInfoItem>"),
							mGxRPDecoder.GetAttributeEventName(rec->xEvent),
							mGxRPDecoder.GetAttributeValue(mpg, rec->xLength, rec->xValue[0], rec->xValue[1]));
						if(!WriteLine(str, 3)) return false;
					}
				}

				str = _T("</gmrpInfo>");
				if(!WriteLine(str, 2)) return false;
			}
		}
	}

	return true;
}
//---------------------------------------------------------------------------

bool ExportXML::AddCDPInfo(MMachineInfo* mmiIn)
{
	CString str;
	int i, cnt;
	int j, jnt;
	MCDPPacket *mpg;
	MTLVRecord *rec;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetCDPPackCount();
	if(cnt==0) return true;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetCDPPack(i);
		if(mpg!=NULL){
			str.Format(_T("<cdpInfo name=\"Device %s, port %s, platform %s\">"),
				mCDPDecoder.FindAndGetTypeValueAsString(mpg, CDPT_DeviceId),
				mCDPDecoder.FindAndGetTypeValueAsString(mpg, CDPT_PortId),
				mCDPDecoder.FindAndGetTypeValueAsString(mpg, CDPT_Platform));
			if(!WriteLine(str, 2)) return false;

			jnt = mpg->xValuesList.GetSize();
			for(j=0; j<jnt; j++){
				rec = mpg->xValuesList.GetByIdx(j);
				if(rec!=NULL){
					str.Format(_T("<cdpInfoItem type=\"%s\">%s</cdpInfoItem>"),
						mCDPDecoder.GetTypeName(rec->xType),
						mCDPDecoder.GetValueName(rec));
					if(!WriteLine(str, 3)) return false;
				}
			}

			str = _T("</cdpInfo>");
			if(!WriteLine(str, 2)) return false;
		}
	}

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddSTPInfo(MMachineInfo* mmiIn)
{
	CString str;
	int i, cnt;
	MSTPPacket *mpg;
	MAddressMAC macAddr;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetSTPPackCount();
	if(cnt==0) return true;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetSTPPack(i);
		if(mpg!=NULL){
			macAddr.LoadFromBytePtr(&(mpg->BridgeIdMAC[0]));

			str.Format(_T("<stpInfo name=\"Bridge ID is %s, priority %s\">"),
				macAddr.GetS(),
				mSTPDecoder.FormatPriorityRaw(mpg->BridgeIdPriority));
			if(!WriteLine(str, 2)) return false;

			str.Format(_T("<stpInfoItem type=\"Protocol ID\">%u</stpInfoItem>"), mpg->ProtocolId);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Version\">%u</stpInfoItem>"), mpg->Version);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Message Type\">%s</stpInfoItem>"), mSTPDecoder.GetMessageTypeName(mpg));
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Flags\">%s</stpInfoItem>"), mSTPDecoder.GetFlagsName(mpg));
			if(!WriteLine(str, 3)) return false;

			macAddr.LoadFromBytePtr(&(mpg->RootIdMAC[0]));
			str.Format(_T("<stpInfoItem type=\"Root ID\">%s</stpInfoItem>"), macAddr.GetS());
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Root Priority\">%s</stpInfoItem>"), mSTPDecoder.FormatPriorityRaw(mpg->RootIdPriority));
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Root Path Cost\">%u</stpInfoItem>"), mpg->RootPathCost);
			if(!WriteLine(str, 3)) return false;

			macAddr.LoadFromBytePtr(&(mpg->BridgeIdMAC[0]));
			str.Format(_T("<stpInfoItem type=\"Bridge ID\">%s</stpInfoItem>"), macAddr.GetS());
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Bridge Priority\">%s</stpInfoItem>"), mSTPDecoder.FormatPriorityRaw(mpg->BridgeIdPriority));
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Port Id\">0x%x</stpInfoItem>"), mpg->PortId);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Message Age[s]\">%u</stpInfoItem>"), mpg->MessageAge>>8);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Maximum Age[s]\">%u</stpInfoItem>"), mpg->MaximumAge>>8);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Hello Time[s]\">%u</stpInfoItem>"), mpg->HelloTime>>8);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<stpInfoItem type=\"Forward Delay[s]\">%u</stpInfoItem>"), mpg->ForwardDelay>>8);
			if(!WriteLine(str, 3)) return false;

			str = _T("</stpInfo>");
			if(!WriteLine(str, 2)) return false;
		}
	}

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddDTPInfo(MMachineInfo* mmiIn)
{
	CString str;
	int i, cnt;
	int j, jnt;
	MDTPPacket *mpg;
	MTLVRecord *rec;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetDTPPackCount();
	if(cnt==0) return true;

	for(i=0; i<cnt; i++){
		mpg = mmiIn->GetDTPPack(i);
		if(mpg!=NULL){
			str.Format(_T("<dtpInfo name=\"MAC %s\">"), mDTPDecoder.GetMacTypeValue(mpg));
			if(!WriteLine(str, 2)) return false;

			jnt = mpg->xValuesList.GetSize();
			for(j=0; j<jnt; j++){
				rec = mpg->xValuesList.GetByIdx(j);
				if(rec!=NULL){
					str.Format(_T("<dtpInfoItem type=\"%s\">%s</dtpInfoItem>"),
						mDTPDecoder.GetTypeName(rec->xType),
						mDTPDecoder.GetValueName(rec));
					if(!WriteLine(str, 3)) return false;
				}
			}

			str = _T("</dtpInfo>");
			if(!WriteLine(str, 2)) return false;
		}
	}

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddDnsNames(MMachineInfo* mmiIn)
{
	CString str;
	bool res;
	int i, cnt;
	MDnsName *dnsName;

	if(mmiIn==NULL) return true;

	cnt = mmiIn->GetDnsNameCount();
	if(cnt<=0) return true;

	str = _T("<dnsNames>");
	res = WriteLine(str, 2);
	if(!res) return false;

	for(i=0; i<cnt; i++){
		dnsName = mmiIn->GetDnsName(i);
		if(dnsName!=NULL){
			str = _T("<dnsName>");
			res = WriteLine(str, 3);
			if(!res) return false;

			str.Format(_T("<dnsNameType>%s</dnsNameType>"), wd.GetDnsQueryTypeName(dnsName->nameType));
			res = WriteLine(str, 4);
			if(!res) return false;

			str.Format(_T("<dnsNameValue>%s</dnsNameValue>"), dnsName->nameDns);
			res = WriteLine(str, 4);
			if(!res) return false;

			str.Format(_T("<dnsNameTTL>%s</dnsNameTTL>"), DwTimeToDHMS(dnsName->nameDnsTTL));
			res = WriteLine(str, 4);
			if(!res) return false;

			str = _T("</dnsName>");
			res = WriteLine(str, 3);
			if(!res) return false;
		}
	}

	str = _T("</dnsNames>");
	res = WriteLine(str, 2);
	if(!res) return false;

	return true;
}

bool ExportXML::ExportMachine(MMachineInfo* mmi, MKOuiIabList* vendorList, MKMcast4List* mcast4List, MPortDescriptionList* portDescList)
{
	CString str;
	bool res;

	if(mmi==NULL) return true;

	str.Format(_T("<result id=\"%d\">"), expHostId);
	expHostId++;
	res = WriteLine(str, 1);
	if(!res) return false;

	if(!mmi->address.addrIP.IsEmpty()){
		str = _T("<addrIP>");
		str += mmi->address.addrIP.GetS();
		str += _T("</addrIP>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}
	if(!mmi->address.addrIPv6.IsEmpty()){
		str = _T("<addrIPv6>");
		str += mmi->address.addrIPv6.GetS();
		str += _T("</addrIPv6>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!mmi->address.gwMAC){
		if(vendorList!=NULL){
			str = _T("<addrMAC type=\"Arp\" vendor=\"");
			str += vendorList->GetVendorName(&(mmi->address.addrMAC));
			str += _T("\">");
		}
		else{
			str = _T("<addrMAC type=\"Arp\">");
		}
		str += mmi->address.addrMAC.GetS();
		str += _T("</addrMAC>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}
	if(!mmi->address.addrMACnb.IsEmpty()){
		if(vendorList!=NULL){
			str = _T("<addrMAC type=\"NetBios\" vendor=\"");
			str += vendorList->GetVendorName(&(mmi->address.addrMAC));
			str += _T("\">");
		}
		else{
			str = _T("<addrMAC type=\"NetBios\">");
		}
		str += mmi->address.addrMACnb.GetS();
		str += _T("</addrMAC>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!mmi->address.addrIPX.IsEmpty()){
		str = _T("<addrIPX>");
		str += mmi->address.addrIPX.GetS();
		str += _T("</addrIPX>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!mmi->countryCode.IsEmpty()){
		str = _T("<countryCode>");
		str += mmi->countryCode;
		str += _T("</countryCode>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!AddPortsForMethod(mmi, __wmtHunt, portDescList)) return false;

	if(!AddDnsNames(mmi)) return false;

	if(mmi->ssdp){
		str = _T("<ssdp/>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(mmi->successfullyStopped){
		str = _T("<stopped/>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	if(!AddNetBiosNames(mmi)) return false;

	if(!AddSharesInfo(mmi)) return false;

	if(!AddSnmpSysInfo(mmi)) return false;

	if(!AddDhcpInfo(mmi)) return false;

	if(!AddPromiscResults(mmi)) return false;

	if(!AddIgmpInfo(mmi, mcast4List)) return false;

	if(!AddGVRPInfo(mmi)) return false;
	if(!AddGMRPInfo(mmi)) return false;

	if(!AddCDPInfo(mmi)) return false;
	if(!AddSTPInfo(mmi)) return false;
	if(!AddDTPInfo(mmi)) return false;

	if(!AddPortsForMethod(mmi, __wmtSyn,          portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtFin,          portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtNull,         portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtXmas,         portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtUdpSend,      portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtIpProtocol,   portDescList)) return false;

	if(!AddPortsForMethod(mmi, __wmt6Syn,         portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmt6Fin,         portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmt6Null,        portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmt6Xmas,        portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmt6UdpSend,     portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmt6Proto,       portDescList)) return false;

	if(!AddPortsForMethod(mmi, __wmtPassiveTCP,   portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtPassiveUDP,   portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtPassiveTCPv6, portDescList)) return false;
	if(!AddPortsForMethod(mmi, __wmtPassiveUDPv6, portDescList)) return false;

	if(!AddWmiInfo(&(mmi->wmiData)))               return false;

	str = _T("</result>");
	res = WriteLine(str, 1);
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

CString ExportXML::GetMethodName(WorkMethodType wmtIn)
{
	return wd.GetMethodName(wmtIn);
}

//---------------------------------------------------------------------------

bool ExportXML::AddPortsForMethod(MMachineInfo* mmi, WorkMethodType wmtIn, MPortDescriptionList* portDescList)
{
	MPortInfo* mpi;
	CString str, portDescStr;
	int i, cnt;
	bool respReceived;
	bool foundOne;
	bool res;

	if(wmtIn==__wmtIpProtocol || wmtIn==__wmt6Proto) cnt = mmi->GetProtoCount();
	else                                             cnt = mmi->GetPortCount();

	foundOne = false;
	for(i=0; i<cnt; i++){
		if(wmtIn==__wmtIpProtocol || wmtIn==__wmt6Proto) mpi = mmi->GetProtoInfo(i);
		else                                             mpi = mmi->GetPortInfo(i);

		if(mpi!=NULL){
			if(mpi->method==wmtIn){
				// found one
				if(!foundOne){
					foundOne = true;

					str.Format(_T("<method name=\"%s\""), GetMethodName(wmtIn));
					switch(wmtIn){
						case __wmtFin :
							respReceived = mmi->recvFin;
							break;

						case __wmtNull :
							respReceived = mmi->recvNull;
							break;

						case __wmtXmas :
							respReceived = mmi->recvXmas;
							break;

						case __wmtUdpSend :
							respReceived = mmi->recvUdpSend;
							break;

						case __wmt6Fin :
							respReceived = mmi->recv6Fin;
							break;

						case __wmt6Null :
							respReceived = mmi->recv6Null;
							break;

						case __wmt6Xmas :
							respReceived = mmi->recv6Xmas;
							break;

						case __wmt6UdpSend :
							respReceived = mmi->recv6UdpSend;
							break;

						case __wmtIpProtocol :
							respReceived = mmi->recvIpProto;
							break;

						case __wmt6Proto :
							respReceived = mmi->recv6NextHeader;
							break;

						default:
							respReceived = true;
							break;
					}
					if(respReceived) str += _T(" respReceived=\"1\"");
					else             str += _T(" respReceived=\"0\"");

					str += _T(">");

					res = WriteLine(str, 2);
					if(!res) return false;
				}

				str = _T("<methodResult>");
				res = WriteLine(str, 3);
				if(!res) return false;

				if(portDescList==NULL) portDescStr.Empty();
				else{
					switch(wmtIn){
						case __wmtIpProtocol :
						case __wmt6Proto :
							portDescStr = portDescList->GetPortDescription(__mpdpProtocol, mpi->port);
							break;

						case __wmtUdpSend :
						case __wmt6UdpSend :
							portDescStr = portDescList->GetPortDescription(__mpdpUdp, mpi->port);
							break;

						default :
							portDescStr = portDescList->GetPortDescription(__mpdpTcp, mpi->port);
							break;
					}
				}

				switch(mpi->method){
					case __wmtSyn:
					case __wmt6Syn:
						str.Format(_T("<methodPort>%d</methodPort>"), mpi->port);
						res = WriteLine(str, 4);
						if(!res) return false;

						str.Format(_T("<methodTime>%d</methodTime>"), mpi->timeInterval);
						res = WriteLine(str, 4);
						if(!res) return false;
						break;

					case __wmtIpProtocol:
					case __wmt6Proto:
						str.Format(_T("<methodProtocol>%d</methodProtocol>"), mpi->port);
						res = WriteLine(str, 4);
						if(!res) return false;
						break;

					default:
						str.Format(_T("<methodPort>%d</methodPort>"), mpi->port);
						res = WriteLine(str, 4);
						if(!res) return false;
						break;
				}

				str.Format(_T("<methodPortName>%s</methodPortName>"), portDescStr);
				res = WriteLine(str, 4);
				if(!res) return false;

				str = _T("</methodResult>");
				res = WriteLine(str, 3);
				if(!res) return false;
			}
		}
	}

	if(foundOne){
		str = _T("</method>");
		res = WriteLine(str, 2);
		if(!res) return false;
	}

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::AddWmiInfoValue(CString nameIn, CString valueIn)
{
	CString str;

	if(valueIn.IsEmpty()) return true;
	if(nameIn.IsEmpty()) return false;

	str.Format(_T("<wmiInfoValue name=\"%s\">%s</wmiInfoValue>"), nameIn, RemoveStupidChars(valueIn));

	return WriteLine(str, 5);
}

bool ExportXML::AddWmiInfo(MWmiData* wmiDataIn)
{
	bool found;
	int qfeCnt, usrCnt, grpCnt;
	CString str;

	if(wmiDataIn==NULL) return false;

	found = false;
		if(!wmiDataIn->wmiCDROMDrive.IsEmpty())          found = true;
		if(!wmiDataIn->wmiDesktopMonitor.IsEmpty())      found = true;
		if(!wmiDataIn->wmiDiskDrive.IsEmpty())           found = true;
		if(!wmiDataIn->wmiDiskPartition.IsEmpty())       found = true;
		if(!wmiDataIn->wmiGroup.IsEmpty())               found = true;
		if(!wmiDataIn->wmiOperatingSystem.IsEmpty())     found = true;
		if(!wmiDataIn->wmiPhysicalMemory.IsEmpty())      found = true;
		if(!wmiDataIn->wmiProcessor.IsEmpty())           found = true;
		if(!wmiDataIn->wmiQuickFixEngineering.IsEmpty()) found = true;
		if(!wmiDataIn->wmiShare.IsEmpty())               found = true;
		if(!wmiDataIn->wmiUserAccount.IsEmpty())         found = true;
		if(!wmiDataIn->wmiVideoController.IsEmpty())     found = true;
		if(!wmiDataIn->wmiLoggedUser.IsEmpty())          found = true;
	if(!found) return true;

	str = _T("<wmiInfo>");
	if(!WriteLine(str, 2)) return false;

	if(!wmiDataIn->wmiOperatingSystem.IsEmpty()){
		str = _T("<wmiInfoOS>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoOS(&(wmiDataIn->wmiOperatingSystem))) return false;
		str = _T("</wmiInfoOS>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiQuickFixEngineering.IsEmpty()){
		qfeCnt = GetWmiInfoQFECount(&(wmiDataIn->wmiQuickFixEngineering));
		str.Format(_T("<wmiInfoQFE cnt=\"%d\">"), qfeCnt);
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoQFE(&(wmiDataIn->wmiQuickFixEngineering))) return false;
		str = _T("</wmiInfoQFE>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiShare.IsEmpty()){
		str = _T("<wmiInfoShare>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoShares(&(wmiDataIn->wmiShare))) return false;
		str = _T("</wmiInfoShare>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiProcessor.IsEmpty()){
		str = _T("<wmiInfoProcessor>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoProcessor(&(wmiDataIn->wmiProcessor))) return false;
		str = _T("</wmiInfoProcessor>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiPhysicalMemory.IsEmpty()){
		str = _T("<wmiInfoPhysicalMemory>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoPhysicalMem(&(wmiDataIn->wmiPhysicalMemory))) return false;
		str = _T("</wmiInfoPhysicalMemory>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiDiskDrive.IsEmpty()){
		str = _T("<wmiInfoDiskDrive>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoDiskDrive(&(wmiDataIn->wmiDiskDrive))) return false;
		str = _T("</wmiInfoDiskDrive>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiDiskPartition.IsEmpty()){
		str = _T("<wmiInfoDiskPartition>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoDiskPart(&(wmiDataIn->wmiDiskPartition))) return false;
		str = _T("</wmiInfoDiskPartition>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiCDROMDrive.IsEmpty()){
		str = _T("<wmiInfoCDROMDrive>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoCDROM(&(wmiDataIn->wmiCDROMDrive))) return false;
		str = _T("</wmiInfoCDROMDrive>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiVideoController.IsEmpty()){
		str = _T("<wmiInfoVideoController>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoVideoController(&(wmiDataIn->wmiVideoController))) return false;
		str = _T("</wmiInfoVideoController>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiDesktopMonitor.IsEmpty()){
		str = _T("<wmiInfoDesktopMonitor>");
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoDesktopMonitor(&(wmiDataIn->wmiDesktopMonitor))) return false;
		str = _T("</wmiInfoDesktopMonitor>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiUserAccount.IsEmpty()){
		usrCnt = GetWmiInfoUserAccountCount(&(wmiDataIn->wmiUserAccount));
		str.Format(_T("<wmiInfoUserAccount cnt=\"%d\">"), usrCnt);
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoUserAccount(&(wmiDataIn->wmiUserAccount))) return false;
		str = _T("</wmiInfoUserAccount>");
		if(!WriteLine(str, 3)) return false;
	}

	if(!wmiDataIn->wmiGroup.IsEmpty()){
		grpCnt = GetWmiInfoGroupCount(&(wmiDataIn->wmiGroup));
		str.Format(_T("<wmiInfoGroup cnt=\"%d\">"), grpCnt);
		if(!WriteLine(str, 3)) return false;
		if(!AddWmiInfoGroup(&(wmiDataIn->wmiGroup))) return false;
		str = _T("</wmiInfoGroup>");
		if(!WriteLine(str, 3)) return false;
	}

	str = _T("</wmiInfo>");
	if(!WriteLine(str, 2)) return false;

	return true;
}

bool ExportXML::AddWmiInfoOS(MWmi_Win32_OperatingSystem* dataIn)
{
	CString str;

	if(dataIn==NULL) return false;

/*
	- CString        xBuildNumber;
	- unsigned int   xOSProductSuite;				// uint32==VT_I4==VARIANT.lVal		MWmiNames::GetOSProductSuiteName
	- unsigned short xOSType;						// uint16==VT_I4==VARIANT.lVal		MWmiNames::GetOSTypeName
*/

	str = _T("<wmiInfoObject>");
	if(!WriteLine(str, 4)) return false;

	if(!dataIn->xCaption.IsEmpty()){
		if(dataIn->xOtherTypeDescription.IsEmpty()) str = dataIn->xCaption;
		else                                        str.Format(_T("%s %s"), dataIn->xCaption, dataIn->xOtherTypeDescription);
		if(!AddWmiInfoValue(_T("Name"), str)) return false;
	}

	if(dataIn->xServicePackMajorVersion!=0 || dataIn->xServicePackMinorVersion!=0){
		if(dataIn->xServicePackMinorVersion==0) str.Format(_T("%d"), dataIn->xServicePackMajorVersion);
		else                                    str.Format(_T("%d.%d"), dataIn->xServicePackMajorVersion, dataIn->xServicePackMinorVersion);
		if(!AddWmiInfoValue(_T("Service Pack"), str)) return false;
	}

	if(!AddWmiInfoValue(_T("Version"),          dataIn->xVersion))        return false;
	if(!AddWmiInfoValue(_T("BuildType"),       dataIn->xBuildType))      return false;
	if(!AddWmiInfoValue(_T("Serial Number"),   dataIn->xSerialNumber))   return false;
	if(!AddWmiInfoValue(_T("Organization"),    dataIn->xOrganization))   return false;
	if(!AddWmiInfoValue(_T("Registered User"), dataIn->xRegisteredUser)) return false;

	if(dataIn->xProductType!=0)
		if(!AddWmiInfoValue(_T("Type"), wmiNames.GetProductTypeName(dataIn->xProductType))) return false;

	if(!AddWmiInfoValue(_T("InstallDate"),      dataIn->xInstallDate))    return false;
	if(!AddWmiInfoValue(_T("LastBootUpTime"),   dataIn->xLastBootUpTime)) return false;

	if(!AddWmiInfoValue(_T("Current Time Zone"), wmiNames.GetTimeZone(dataIn->xCurrentTimeZone))) return false;

	if(!dataIn->xTotalVisibleMemorySize.IsEmpty()){
		str.Format(_T("%d"), dataIn->GetSizeM_OS(dataIn->xTotalVisibleMemorySize));
		if(!AddWmiInfoValue(_T("Total Visible Memory [MB]"), str)) return false;
	}
	
	if(!AddWmiInfoValue(_T("BootDevice"),       dataIn->xBootDevice))       return false;
	if(!AddWmiInfoValue(_T("SystemDevice"),     dataIn->xSystemDevice))     return false;
	if(!AddWmiInfoValue(_T("SystemDrive"),      dataIn->xSystemDrive))      return false;
	if(!AddWmiInfoValue(_T("SystemDirectory"),  dataIn->xSystemDirectory))  return false;
	if(!AddWmiInfoValue(_T("WindowsDirectory"), dataIn->xWindowsDirectory)) return false;
	if(!AddWmiInfoValue(_T("Computer name"),    dataIn->xCSName))           return false;

	str = _T("</wmiInfoObject>");
	if(!WriteLine(str, 4)) return false;

	return true;
}

bool ExportXML::AddWmiInfoQFE(MWmi_Win32_QuickFixEngineering* dataIn)
{
	MWmi_Win32_QuickFixEngineering* data;
	CString str;
	bool wrongSetting;

	if(dataIn==NULL) return false;

	wrongSetting = false;
	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		str = data->xHotFixID;
		if(str.CompareNoCase(_T("File 1"))==0){
			if(!data->xServicePackInEffect.IsEmpty()){
				str = data->xServicePackInEffect;
				wrongSetting = true;
			}
		}
		if(!AddWmiInfoValue(_T("Name"), str)) return false;

		if(!wrongSetting)
			if(!AddWmiInfoValue(_T("Service Pack"), data->xServicePackInEffect)) return false;

		if(!AddWmiInfoValue(_T("Description"), data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Comments"),    data->xFixComments)) return false;
		if(!AddWmiInfoValue(_T("Installed by"), data->xInstalledBy)) return false;
		if(!AddWmiInfoValue(_T("Installed on"), data->xInstalledOn)) return false;

		data = (MWmi_Win32_QuickFixEngineering*)data->next;
		
		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

int ExportXML::GetWmiInfoQFECount(MWmi_Win32_QuickFixEngineering* dataIn)
{
	MWmi_Win32_QuickFixEngineering* data;
	int cnt;

	if(dataIn==NULL) return 0;

	cnt = 0;
	data = dataIn;
	while(data!=NULL){
		cnt++;
		data = (MWmi_Win32_QuickFixEngineering*)data->next;
	}

	return cnt;
}

bool ExportXML::AddWmiInfoShares(MWmi_Win32_Share* dataIn)
{
	MWmi_Win32_Share* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),         data->xName)) return false;
		if(!AddWmiInfoValue(_T("Path"),        data->xPath)) return false;
		if(!AddWmiInfoValue(_T("Description"), data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Type"),        wmiNames.GetShareTypeName(data->xType))) return false;

		if(data->xAllowMaximum) str = _T("Maximum");
		else                    str.Format(_T("%d"), data->xMaximumAllowed);
		if(!AddWmiInfoValue(_T("Allowed count"), str)) return false;

		data = (MWmi_Win32_Share*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoDiskDrive(MWmi_Win32_DiskDrive* dataIn)
{
	MWmi_Win32_DiskDrive* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName)) return false;
		if(!AddWmiInfoValue(_T("Description"),  data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Manufacturer"), data->xManufacturer)) return false;
		if(!AddWmiInfoValue(_T("Model"),        data->xModel)) return false;

		if(!data->xSize.IsEmpty())
			if(!AddWmiInfoValue(_T("Size"), wmiNames.GetDiskSizeHuman(data->xSize))) return false;

		if(data->xPartitions!=0){
			str.Format(_T("%d"), data->xPartitions);
			if(!AddWmiInfoValue(_T("Partitions"), str)) return false;
		}

		if(data->xSignature!=0){
			str.Format(_T("%d"), data->xSignature);
			if(!AddWmiInfoValue(_T("Signature"), str)) return false;
		}

		data = (MWmi_Win32_DiskDrive*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoDiskPart(MWmi_Win32_DiskPartition* dataIn)
{
	MWmi_Win32_DiskPartition* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName)) return false;
		if(!AddWmiInfoValue(_T("Description"), data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Type"), data->xType)) return false;

		if(!data->xSize.IsEmpty())
			if(!AddWmiInfoValue(_T("Size"), wmiNames.GetDiskSizeHuman(data->xSize))) return false;

		if(!data->xStartingOffset.IsEmpty())
			if(!AddWmiInfoValue(_T("Starting offset"), data->xStartingOffset)) return false;
		if(!data->xNumberOfBlocks.IsEmpty())
			if(!AddWmiInfoValue(_T("Number of blocks"), data->xNumberOfBlocks)) return false;

		if(data->xPrimaryPartition)
			if(!AddWmiInfoValue(_T("Primary partition"), _T("true"))) return false;
		if(data->xBootable)
			if(!AddWmiInfoValue(_T("Bootable"), _T("true"))) return false;
		if(data->xBootPartition)
			if(!AddWmiInfoValue(_T("Boot partition"), _T("true"))) return false;

		data = (MWmi_Win32_DiskPartition*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoProcessor(MWmi_Win32_Processor* dataIn)
{
	MWmi_Win32_Processor* data;
	CString str;

/*
	unsigned short xAddressWidth;
	unsigned short xCurrentVoltage;
	unsigned short xDataWidth;
	unsigned short xLevel;
	unsigned short xLoadPercentage;
	unsigned short xRevision;
	CString        xStepping;
	CString        xVersion;
*/

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName.Trim())) return false;

		if(!AddWmiInfoValue(_T("Manufacturer"), data->xManufacturer)) return false;
		if(!AddWmiInfoValue(_T("Description"),  data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Processor ID"), data->xProcessorId)) return false;
		if(!AddWmiInfoValue(_T("Device ID"),    data->xDeviceID)) return false;

		if(data->xMaxClockSpeed!=0){
			str.Format(_T("%d"), data->xMaxClockSpeed);
			if(!AddWmiInfoValue(_T("Clock speed"), str)) return false;
		}
		if(data->xCurrentClockSpeed!=0){
			str.Format(_T("%d"), data->xCurrentClockSpeed);
			if(!AddWmiInfoValue(_T("Current clock speed"), str)) return false;
		}
		if(data->xExtClock!=0){
			str.Format(_T("%d"), data->xExtClock);
			if(!AddWmiInfoValue(_T("External clock speed"), str)) return false;
		}

		if(data->xArchitecture!=0)
			if(!AddWmiInfoValue(_T("Architecture"), wmiNames.GetArchitectureName(data->xArchitecture))) return false;

		if(data->xFamily!=0){
			if(data->xFamily==1)
				if(!AddWmiInfoValue(_T("Family"), data->xOtherFamilyDescription)) return false;
			else
				if(!AddWmiInfoValue(_T("Family"), wmiNames.GetFamilyName(data->xFamily))) return false;
		}

		if(data->xProcessorType!=0)
			if(!AddWmiInfoValue(_T("Family"), wmiNames.GetProcessorTypeName(data->xProcessorType))) return false;

		if(data->xVoltageCaps!=0)
			if(!AddWmiInfoValue(_T("Voltage caps."), wmiNames.GetVoltageCapsName(data->xVoltageCaps))) return false;
		
		if(data->xCpuStatus!=0)
			if(!AddWmiInfoValue(_T("Status"), wmiNames.GetCpuStatusName(data->xCpuStatus))) return false;

		data = (MWmi_Win32_Processor*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoPhysicalMem(MWmi_Win32_PhysicalMemory* dataIn)
{
	MWmi_Win32_PhysicalMemory* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName)) return false;

		if(!AddWmiInfoValue(_T("Description"), data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Size"), wmiNames.GetMemSizeHuman(data->xCapacity))) return false;

		if(data->xSpeed!=0){
			str.Format(_T("%d"), data->xSpeed);
			if(!AddWmiInfoValue(_T("Speed [ns]"), str)) return false;
		}

		if(!AddWmiInfoValue(_T("Location"), data->xDeviceLocator)) return false;
		if(!AddWmiInfoValue(_T("Tag"), data->xTag)) return false;

		if(data->xMemoryType!=0)
			if(!AddWmiInfoValue(_T("Memory type"), wmiNames.GetMemoryTypeName(data->xMemoryType))) return false;
		if(data->xTypeDetail!=0)
			if(!AddWmiInfoValue(_T("Type detail"), wmiNames.GetTypeDetailName(data->xTypeDetail))) return false;
		if(data->xFormFactor!=0)
			if(!AddWmiInfoValue(_T("Form factor"), wmiNames.GetFormFactorName(data->xFormFactor))) return false;

		if(data->xDataWidth!=0){
			str.Format(_T("%d"), data->xDataWidth);
			if(!AddWmiInfoValue(_T("Data width [bits]"), str)) return false;
		}
		if(data->xTotalWidth!=0){
			str.Format(_T("%d"), data->xTotalWidth);
			if(!AddWmiInfoValue(_T("Total width [bits]"), str)) return false;
		}

		data = (MWmi_Win32_PhysicalMemory*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoCDROM(MWmi_Win32_CDROMDrive* dataIn)
{
	MWmi_Win32_CDROMDrive* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName)) return false;
		if(!AddWmiInfoValue(_T("Manufacturer"), data->xManufacturer)) return false;
		if(!AddWmiInfoValue(_T("Description"),  data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Drive"),        data->xDrive)) return false;
		if(!AddWmiInfoValue(_T("MediaType"),    data->xMediaType)) return false;
		if(data->xMediaLoaded){
			if(!AddWmiInfoValue(_T("VolumeName"),         data->xVolumeName)) return false;
			if(!AddWmiInfoValue(_T("Size"),               data->xSize)) return false;
			if(!AddWmiInfoValue(_T("VolumeSerialNumber"), data->xVolumeSerialNumber)) return false;
		}

		data = (MWmi_Win32_CDROMDrive*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoVideoController(MWmi_Win32_VideoController* dataIn)
{
	MWmi_Win32_VideoController* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),            data->xName)) return false;
		if(!AddWmiInfoValue(_T("Description"),     data->xDescription)) return false;
		if(!AddWmiInfoValue(_T("Video Processor"), data->xVideoProcessor)) return false;
		if(data->xAdapterRAM!=0){
			str.Format(_T("%d MB"), data->xAdapterRAM/1048576);
			if(!AddWmiInfoValue(_T("Adapter RAM"), str)) return false;
		}
		if(data->xCurrentHorizontalResolution!=0){
			str.Format(_T("%d x %d, %d bpp"), data->xCurrentHorizontalResolution, data->xCurrentVerticalResolution, data->xCurrentBitsPerPixel);
			if(!AddWmiInfoValue(_T("Current resolution"), str)) return false;
		}
		if(data->xCurrentRefreshRate!=0){
			str.Format(_T("%d"), data->xCurrentRefreshRate);
			if(!AddWmiInfoValue(_T("Current refresh rate [Hz]"), str)) return false;
		}

		if(!AddWmiInfoValue(_T("Installed display drivers"), data->xInstalledDisplayDrivers)) return false;
		if(!AddWmiInfoValue(_T("Driver version"),            data->xDriverVersion))           return false;
		if(!AddWmiInfoValue(_T("Driver date"),               data->xDriverDate))              return false;
		if(!AddWmiInfoValue(_T("Inf filename"),              data->xInfFilename))             return false;
		if(!AddWmiInfoValue(_T("Inf section"),               data->xInfSection))              return false;

		data = (MWmi_Win32_VideoController*)data->next;

		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoDesktopMonitor(MWmi_Win32_DesktopMonitor* dataIn)
{
	MWmi_Win32_DesktopMonitor* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),          data->xName)) return false;
		if(!AddWmiInfoValue(_T("Manufacturer"), data->xMonitorManufacturer)) return false;
		if(!AddWmiInfoValue(_T("Type"),         data->xMonitorType)) return false;
		if(!AddWmiInfoValue(_T("Description"),  data->xDescription)) return false;

		if(data->xScreenWidth!=0){
			str.Format(_T("%d x %d"), data->xScreenWidth, data->xScreenHeight);
			if(!AddWmiInfoValue(_T("Resolution"), str)) return false;
		}
		if(data->xPixelsPerXLogicalInch!=0){
			str.Format(_T("%d x %d"), data->xPixelsPerXLogicalInch, data->xPixelsPerYLogicalInch);
			if(!AddWmiInfoValue(_T("Pixels per logical inch"), str)) return false;
		}

		data = (MWmi_Win32_DesktopMonitor*)data->next;
	
		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

bool ExportXML::AddWmiInfoUserAccount(MWmi_Win32_UserAccount* dataIn)
{
	MWmi_Win32_UserAccount* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = data->xName;
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),               FormatTextString(data->xName))) return false;
		if(!AddWmiInfoValue(_T("Disabled"),           data->xDisabled ? _T("true") : _T("false"))) return false;
		if(!AddWmiInfoValue(_T("Account locked out"), data->xLockout  ? _T("true") : _T("false"))) return false;

		if(!AddWmiInfoValue(_T("Description"), FormatTextString(data->xDescription))) return false;
		if(!AddWmiInfoValue(_T("Domain"),      data->xDomain)) return false;
		if(!AddWmiInfoValue(_T("Full name"),   data->xFullName)) return false;
		if(!AddWmiInfoValue(_T("SID"),         data->xSID)) return false;

		if(!data->xSIDType!=0)
			if(!AddWmiInfoValue(_T("SID Type"), wmiNames.GetSIDTypeName(data->xSIDType))) return false;

		if(!AddWmiInfoValue(_T("Account Type"), wmiNames.GetAccountTypeName(data->xAccountType))) return false;

		if(!AddWmiInfoValue(_T("Local account"),       data->xLocalAccount       ? _T("true") : _T("false"))) return false;
		if(!AddWmiInfoValue(_T("Password changeable"), data->xPasswordChangeable ? _T("true") : _T("false"))) return false;
		if(!AddWmiInfoValue(_T("Password expires"),    data->xPasswordExpires    ? _T("true") : _T("false"))) return false;
		if(!AddWmiInfoValue(_T("Password required"),   data->xPasswordRequired   ? _T("true") : _T("false"))) return false;

		if(!AddWmiInfoValue(_T("Status"), data->xStatus)) return false;

		data = (MWmi_Win32_UserAccount*)data->next;
	
		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

int ExportXML::GetWmiInfoUserAccountCount(MWmi_Win32_UserAccount* dataIn)
{
	MWmi_Win32_UserAccount* data;
	int cnt;

	if(dataIn==NULL) return 0;

	cnt = 0;
	data = dataIn;
	while(data!=NULL){
		cnt++;
		data = (MWmi_Win32_UserAccount*)data->next;
	}

	return cnt;
}

bool ExportXML::AddWmiInfoGroup(MWmi_Win32_Group* dataIn)
{
	MWmi_Win32_Group* data;
	CString str;

	if(dataIn==NULL) return false;

	data = dataIn;
	while(data!=NULL){
		str = _T("<wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;

		if(!AddWmiInfoValue(_T("Name"),        FormatTextString(data->xName))) return false;
		if(!AddWmiInfoValue(_T("Description"), FormatTextString(data->xDescription))) return false;
		if(!AddWmiInfoValue(_T("Domain"),      data->xDomain)) return false;
		if(!AddWmiInfoValue(_T("SID"),         data->xSID)) return false;

		if(!data->xSIDType!=0)
			if(!AddWmiInfoValue(_T("SID Type"), wmiNames.GetSIDTypeName(data->xSIDType))) return false;

		if(!AddWmiInfoValue(_T("Local account"), data->xLocalAccount ? _T("true") : _T("false"))) return false;

		if(!AddWmiInfoValue(_T("Status"), data->xStatus)) return false;

		data = (MWmi_Win32_Group*)data->next;
	
		str = _T("</wmiInfoObject>");
		if(!WriteLine(str, 4)) return false;
	}

	return true;
}

int ExportXML::GetWmiInfoGroupCount(MWmi_Win32_Group* dataIn)
{
	MWmi_Win32_Group* data;
	int cnt;

	if(dataIn==NULL) return 0;

	cnt = 0;
	data = dataIn;
	while(data!=NULL){
		cnt++;
		data = (MWmi_Win32_Group*)data->next;
	}

	return cnt;
}

CString ExportXML::FormatTextString(CString strIn)
{
	CString str;

	str = strIn;
	str.Replace(_T("&"), _T("&amp;"));

	return str;
}

//---------------------------------------------------------------------------

bool ExportXML::ExportGlobalInfo(MGlobalInfo* giIn)
{
	CString str;
	bool res;

	if(giIn==NULL) return true;

	str = _T("<globalInfo>");
	res = WriteLine(str, 1);
	if(!res) return false;

	if(!giIn->ethernetCounters.IsEmpty()){
		str = _T("<giEthCnt>");
		if(!WriteLine(str, 2)) return false;

			str.Format(_T("<gieCnt type=\"Arp\">%d</gieCnt>"),    (unsigned int)giIn->ethernetCounters.cntARP);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gieCnt type=\"Tcp4\">%d</gieCnt>"),   (unsigned int)giIn->ethernetCounters.cntTCPv4);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Udp4\">%d</gieCnt>"),   (unsigned int)giIn->ethernetCounters.cntUDPv4);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Icmp4\">%d</gieCnt>"),  (unsigned int)giIn->ethernetCounters.cntICMPv4);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Other4\">%d</gieCnt>"), (unsigned int)giIn->ethernetCounters.cntIPv4Other);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gieCnt type=\"Tcp6\">%d</gieCnt>"),   (unsigned int)giIn->ethernetCounters.cntTCPv6);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Udp6\">%d</gieCnt>"),   (unsigned int)giIn->ethernetCounters.cntUDPv6);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Icmp6\">%d</gieCnt>"),  (unsigned int)giIn->ethernetCounters.cntICMPv6);
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gieCnt type=\"Other6\">%d</gieCnt>"), (unsigned int)giIn->ethernetCounters.cntIPv6Other);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gieCnt type=\"Other\">%d</gieCnt>"),  (unsigned int)giIn->ethernetCounters.cntEthOther);
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gieCnt type=\"Total\">%d</gieCnt>"),  (unsigned int)giIn->ethernetCounters.GetTotalCount());
			if(!WriteLine(str, 3)) return false;

		str = _T("</giEthCnt>");
		if(!WriteLine(str, 2)) return false;
	}

	if(!giIn->ntpIP.IsEmpty()){
		str = _T("<giNTP>");
		if(!WriteLine(str, 2)) return false;

			str.Format(_T("<gin type=\"IP\">%s</gin>"),              giIn->ntpIP.GetS());
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"MAC\">%s</gin>"),             giIn->ntpMAC.GetS());
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gin type=\"Stratum\">%s</gin>"),         mNTPDecoder.GetStratumName(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gin type=\"Poll\">%s</gin>"),            mNTPDecoder.GetPollingInterval(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"Precision\">%s</gin>"),       mNTPDecoder.GetPrecision(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"RootDelay\">%s</gin>"),       mNTPDecoder.GetRootDelay(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"RootDisp\">%s</gin>"),        mNTPDecoder.GetRootDispersion(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;

			str.Format(_T("<gin type=\"ReferenceTstamp\">%s</gin>"), mNTPDecoder.GetReferenceTimestamp(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"OriginateTstamp\">%s</gin>"), mNTPDecoder.GetOriginateTimestamp(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"ReceiveTstamp\">%s</gin>"),   mNTPDecoder.GetReceiveTimestamp(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;
			str.Format(_T("<gin type=\"TransmitTstamp\">%s</gin>"),  mNTPDecoder.GetTransmitTimestamp(&(giIn->ntpMessage)));
			if(!WriteLine(str, 3)) return false;

		str = _T("</giNTP>");
		if(!WriteLine(str, 2)) return false;
	}

	str = _T("</globalInfo>");
	res = WriteLine(str, 1);
	if(!res) return false;

	return true;
}

//---------------------------------------------------------------------------

bool ExportXML::EndExport(void)
{
	bool res;

	if(outFile.m_hFile==CFile::hFileNull) return true;

	res = WriteLine(_T("</CHScannerDoc>"), 0);
	outFile.Flush();
	outFile.Close();
	outFile.m_hFile=CFile::hFileNull;

	return res;
}

//---------------------------------------------------------------------------

CString ExportXML::DwTimeToDHMS(DWORD dwIn)
{
	CString str, sss;
	DWORD rem;
	int dd, hh, mm, ss;

	rem = dwIn;
	dd = 0;
	hh = 0;
	mm = 0;
	ss = 0;
	str.Empty();

	while(rem>=86400){
		dd++;
		rem -= 86400;
	}
	switch(dd){
		case 0:
			str.Empty();
			break;
		case 1:
			str = "1 day";
			break;
		default:
			str.Format(_T("%d days"), dd);
			break;
	}
	if(rem==0) return str;
	
	if(dd!=0) str += " ";

	while(rem>=3600){
		hh++;
		rem -=3600;
	}
	switch(hh){
		case 0:
			break;
		case 1:
			str += "1 hour";
			break;
		default:
			sss.Format(_T("%d hours"), hh);
			str += sss;
			break;
	}
	if(rem==0) return str;

	if(hh!=0) str += " ";

	while(rem>=60){
		mm++;
		rem -=60;
	}
	switch(mm){
		case 0:
			break;
		case 1:
			str += "1 minute";
			break;
		default:
			sss.Format(_T("%d minutes"), mm);
			str += sss;
			break;
	}
	if(rem==0) return str;

	if(mm!=0) str += " ";

	ss = rem;
	switch(ss){
		case 0:
			break;
		case 1:
			str += "1 second";
			break;
		default:
			sss.Format(_T("%d seconds"), ss);
			str += sss;
			break;
	}

	return str;
}

//---------------------------------------------------------------------------

CString ExportXML::DwToIpStr(DWORD dwIn)
{
	CString str;
	in_addr ia;

	ia.S_un.S_addr = dwIn;
	str = inet_ntoa(ia);
	return str;
}

//---------------------------------------------------------------------------
